// sdump.cpp
// Program to dump the contents serialized using Serializer.
//
// Copyright (C) 2008  Maksim Sipos <msipos@mailc.net>
//
// This file is a part of the Ripe language project.
//
// Ripe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "util/standard.hpp"
#include <fstream>
#include <cstdlib>
#include <cstdio>
#include <getopt.h>
#include "util/error.hpp"
#include "util/serialize.hpp"

using namespace Ripe;
using std::printf;
using std::istream;
using std::ifstream;

// Display help message.
void help_message(char* arg1)
{
  printf("Usage: %s FILES\n"
         "Dump a Ripe serialized file to standard output.\n"
         "\n"
         "Possible options:\n"
         "  -h, --help      Display this message.\n"
         "\n"
         "Report bugs to <msipos@mailc.net>\n", arg1);
}

// Dump the given stream
void dump(istream* str)
{
  ISerializer ser(str);
  uint16_t marker;
  
  while ( (marker = ser.detect()) != M_EOF ) {
    switch (marker){
      case M_UINT32:
        printf("UINT32:\t%" PRIu32 "\n", ser.unserialize_uint32());
        break;
      case M_INT32:
        printf(" INT32:\t%" PRId32 "\n", ser.unserialize_int32());
        break;
      case M_UINT16:
        printf("UINT16:\t%" PRIu16 "\n", ser.unserialize_uint16());
        break;
      case M_INT16:
        printf(" INT16:\t%" PRId16 "\n", ser.unserialize_int16());
        break;
      case M_STRING:
        printf("STRING:\t'%s'\n", ser.unserialize_string());
        break;
      default:
        throw ErrorInvalidSerialize();
    }
  }
}

int main(int argc, char** argv)
{
  error_init(argv[0]);

  struct option long_options[] =
    {
      {"help", no_argument, 0, 'h'},
      {0, 0, 0, 0}
    };
  // getopt_long stores the option index here.
  int option_index = 0;

  while(true){
    int c = getopt_long(argc, argv, "h", long_options, &option_index);

    // End of long/short options, remainder of the arguments should be
    // interpreted like input files.
    if (c == EOF){
      break;
    }

    switch(c){
      case 'h':
        help_message(argv[0]);
        return 0;

      default:
       error("Parsing command-line arguments failed.");
        return 1;
    }
  }

  if (optind >= argc){
    error("No input files specified.");
    return 1;
  }

  int arg = optind;
  while (arg < argc){
    try {
      ifstream f(argv[arg], ifstream::in | ifstream::binary);
      printf("  Dump of '%s':\n", argv[arg]);
      dump(&f);
    } catch (const ErrorInvalidSerialize& e) {
      error("Data in '%s' corrupt: %s", argv[arg], e.what());
    }
    arg++;
  }
}
